package team.lourd.network.system.batch.ext;

import team.lourd.network.system.batch.domian.ProcessCondition;
import team.lourd.network.system.batch.domian.ProcessMeta;
import team.lourd.network.system.batch.domian.ProcessPath;
import team.lourd.network.system.batch.ext.support.*;
import team.lourd.network.system.batch.logic.ConditionType;
import team.lourd.network.system.own.domain.pretrem.PMType;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 基本的核心处理器
 * 处理网元的主要处理器,他主要协同
 *
 * @author JADemo
 * @date 2019/2/21 10:19
 * @see ConditionAnalyser 条件解析器
 * @see ConditionExecutor 条件执行器
 * @see ProcessExecutor 表达式执行器
 * @see ParameterResolver 参数解析器
 * 在处理网元的时候BaseCoreHandler会选择最合适的解析器或者执器去完成执行
 * 在基础的CoreHandler里面默认注册了
 * @see LogicConditionExecutor 基于逻辑表达式的条件执行器
 * @see LogicConditionAnalyser 基于逻辑表达式的条件解析器
 * @see JsonObjectParameterResolver 基于JSONObject类型的参数解析器
 * @see BaseProcessExecutor 最基本的表达式执行器
 * 进行处理网元
 */
public class BaseCoreHandler {

    // 当前对象,对象唯一
    private final static BaseCoreHandler source = new BaseCoreHandler();

    static {
        /**
         *  默认添加处理器,后续添加处理器请使用
         * {@link #addConditionExecutor(int, List)}
         * {@link #addProcessExecutor(int, List)}
         * {@link #addParameterResolver(int, List)}
         * */
        source.conditionExecutors.add(ConditionExecutorBuilder.build("Or"));
        source.processExecutors.add(ProcessExecutorBuilder.build());
        source.parameterResolvers.add(new JsonObjectParameterResolver());
    }

    // 当前表达式执行器集合
    private List<ProcessExecutor> processExecutors = new LinkedList<>();
    // 当前条件判断执行器集合
    private List<ConditionExecutor> conditionExecutors = new LinkedList<>();
    // 当前参数解析集合
    private List<ParameterResolver> parameterResolvers = new LinkedList<>();

    // 添加表达式处理器,匹配按先后顺序执行,一旦匹配到处理器就会放弃匹配后面的,推荐选择合适的Index键入
    public void addProcessExecutor(int index, List<ProcessExecutor> processExecutors) {
        this.processExecutors.addAll(index, processExecutors);
    }

    // 添加条件判断执行器,匹配按先后顺序执行,一旦匹配到处理器就会放弃匹配后面的,推荐选择合适的Index键入
    public void addConditionExecutor(int index, List<ConditionExecutor> conditionExecutors) {
        this.conditionExecutors.addAll(index, conditionExecutors);
    }

    // 添加参数解析器,匹配按先后顺序执行,一旦匹配到处理器就会放弃匹配后面的,推荐选择合适的Index键入
    public void addParameterResolver(int index, List<ParameterResolver> parameterResolvers) {
        this.parameterResolvers.addAll(index, parameterResolvers);
    }

    // 处理网元模型
    public boolean handle(ProcessMeta processMeta) {
        // 获取第一次处理结果
        List<ProcessMeta> processMetas = doHandler(Arrays.asList(processMeta));
        try {
            // 如果分支下面还有元素就一直执行
            while (processMetas.size() != 0) {
                processMetas = doHandler(processMetas);
            }
        } catch (Exception e) {
            e.printStackTrace();
            // 发生异常结束
            return false;
        }
        // 处理完毕
        return true;

    }
    // 判断单个条件
    public Boolean stepCondition(String condition, Map<String, Object> json){
        ProcessCondition processCondition  = new ProcessCondition();
        processCondition.setParameters(json);
        processCondition.setType(ConditionType.SIMPLE);
        processCondition.setContent(condition);
        ConditionExecutor executor = getConditionExecutor(processCondition);
        Boolean b = executor.execute(processCondition);
        return b;
    }
    // 处理单个预处理模型
    public Object step(String command, Map<String, Object> json) {
        int prefixIndex = command.indexOf("#{");
        int suffixIndex = command.indexOf("}");
        while (command.contains("#{")) {
            command = command.substring(0, prefixIndex) + json.get(command.substring(prefixIndex + 2, suffixIndex)) + command.substring(suffixIndex + 1);
        }
        ProcessMeta processMeta = new ProcessMeta();
        processMeta.setProcessExpression(command);
        processMeta.setTarget(command);
        processMeta.setType(PMType.API);
        ProcessExecutor processExecutor = getProcessExecutor(processMeta);
        ReturnValue returnValue = processExecutor.execute(processMeta);
        if (returnValue.getState() == 0) {
            return returnValue.getResult();
        } else {
            throw new RuntimeException("无法访问的接口");
        }
    }

    // 挑选出最适合当前元素的处理器
    protected ProcessExecutor getProcessExecutor(ProcessMeta processMeta) {
        return processExecutors.stream().filter((subProcessExecutor) -> {
            return subProcessExecutor.support(processMeta);
        }).collect(Collectors.toList()).get(0);
    }

    // 挑选出最适合当前条件的条件执行器
    protected ConditionExecutor getConditionExecutor(ProcessCondition processCondition) {
        return conditionExecutors.stream().filter((conditionExecutor) -> {
            return conditionExecutor.support(processCondition);
        }).collect(Collectors.toList()).get(0);
    }

    // 挑选出最适合当前条件的参数解析器
    protected ParameterResolver getParameterResolver(ReturnValue returnValue) {
        return parameterResolvers.stream().filter((parameterResolver) -> {
            return parameterResolver.support(returnValue.getType());
        }).collect(Collectors.toList()).get(0);
    }

    // 执行处理,返回节点下面其他的子节点
    protected List<ProcessMeta> doHandler(List<ProcessMeta> processMetas) {
        // 返回的结果集合
        final List<ProcessMeta> results = new ArrayList<>();
        processMetas.stream().forEach(subProcessMeta -> {
            // 挑选出合适的执行器
            ProcessExecutor processExecutor = getProcessExecutor(subProcessMeta);
            // 执行
            ReturnValue returnValue = processExecutor.execute(subProcessMeta);
            // 判断执行结果状态,0 : 正常返回
            if (returnValue.getState() == 0) {
                // 获取当前元素下面的所有路径
                List<ProcessPath> processPaths = subProcessMeta.getProcessPaths();
                processPaths.stream().forEach(processPath -> {
                    // 获取每一个路径的条件表达式
                    ProcessCondition processCondition = processPath.getProcessConditions().get(0);
                    // 挑选出合适的条件执行器
                    ConditionExecutor conditionExecutor = getConditionExecutor(processCondition);
                    // 获取当前参数解析器
                    ParameterResolver resolver = getParameterResolver(returnValue);
                    // 解析参数为Map
                    Map<String, Object> parameter = resolver.resolve(returnValue.getResult());
                    // 设置参数
                    processCondition.setParameters(parameter);
                    // 执行返回执行结果
                    boolean b = conditionExecutor.execute(processCondition);
                    // 如果条件成立,获取路径下面的元素对象,执行下一次doHandler操作
                    if (b) {
                        // 获取下一个节点的元素
                        ProcessMeta processMeta = processPath.getNext();
                        // 设置参数
                        processMeta.setParameter(parameter);
                        // 添加到下一次执行列表中去
                        results.add(processMeta);
                    } else {
                        // 如果条件不成立,程序无法继续进行下去
                        throw new RuntimeException("条件" + processCondition.getContent() + "无法成立,处理停止,请检查参数");
                    }
                });
            } else {
                throw new RuntimeException("无法访问的接口");
            }
        });
        // 返回结果
        return results;
    }

    private BaseCoreHandler() {
    }

    public final static BaseCoreHandler getBaseCoreHandler() {
        return source;
    }


}
